package com.rickpan.controller;

import com.rickpan.dto.common.ApiResponse;
import com.rickpan.dto.request.BatchMoveRequest;
import com.rickpan.dto.request.CreateFolderRequest;
import com.rickpan.dto.request.RenameFileRequest;
import com.rickpan.dto.request.MoveFileRequest;
import com.rickpan.dto.response.FileListResponse;
import com.rickpan.dto.response.FileInfoDTO;
import com.rickpan.dto.response.StorageStatsResponse;
import com.rickpan.entity.FileInfo;
import com.rickpan.entity.User;
import com.rickpan.repository.FileInfoRepository;
import com.rickpan.repository.UserRepository;
import com.rickpan.service.FileManagementService;
import com.rickpan.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import java.util.Map;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 文件管理控制器
 * 处理文件的CRUD操作
 */
@RestController
@RequestMapping("/api/files")
public class FileManagementController {
    
    private static final Logger logger = LoggerFactory.getLogger(FileManagementController.class);
    
    @Autowired
    private FileManagementService fileManagementService;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private FileInfoRepository fileInfoRepository;
    
    /**
     * 获取文件列表
     * GET /api/files
     */
    @GetMapping
    public ResponseEntity<ApiResponse<FileListResponse>> getFileList(
            @RequestParam(required = false) Long parentId,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size,
            @RequestParam(required = false) String search,
            @RequestParam(defaultValue = "updatedAt") String orderBy,
            @RequestParam(defaultValue = "desc") String orderDirection) {
        
        try {
            Long userId = SecurityUtils.getCurrentUserId();
            logger.debug("获取文件列表: userId={}, parentId={}, page={}, size={}", 
                        userId, parentId, page, size);
            
            // 获取文件列表
            Page<FileInfo> filePage = fileManagementService.getFileList(
                    userId, parentId, page, size, search, orderBy, orderDirection);
            
            // 获取用户存储信息
            User user = userRepository.findById(userId).orElse(null);
            
            // 转换为DTO
            List<FileInfoDTO> fileInfoDTOs = filePage.getContent().stream()
                    .map(FileInfoDTO::from)
                    .collect(Collectors.toList());

            logger.debug("查询到 {} 个文件", fileInfoDTOs.size());

            // 构建响应
            FileListResponse response = new FileListResponse();
            response.setContent(fileInfoDTOs);
            response.setTotalElements(filePage.getTotalElements());
            response.setTotalPages(filePage.getTotalPages());
            response.setCurrentPage(filePage.getNumber());
            
            if (user != null) {
                FileListResponse.StorageInfo storageInfo = new FileListResponse.StorageInfo();
                storageInfo.setUsed(user.getStorageUsed());
                storageInfo.setQuota(user.getStorageQuota());
                storageInfo.setPercentage(calculateStoragePercentage(user.getStorageUsed(), user.getStorageQuota()));
                response.setStorageInfo(storageInfo);
            }
            
            logger.debug("返回文件列表响应: success=true, fileCount={}", fileInfoDTOs.size());
            return ResponseEntity.ok(ApiResponse.success(response));
            
        } catch (Exception e) {
            logger.error("获取文件列表失败", e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("获取文件列表失败: " + e.getMessage()));
        }
    }
    
    /**
     * 创建文件夹
     * POST /api/files/folder
     */
    @PostMapping("/folder")
    public ResponseEntity<ApiResponse<FileInfoDTO>> createFolder(@Valid @RequestBody CreateFolderRequest request) {
        try {
            Long userId = SecurityUtils.getCurrentUserId();
            logger.info("用户 {} 创建文件夹: {}", userId, request.getFolderName());

            FileInfo folder = fileManagementService.createFolder(
                    userId, request.getFolderName(), request.getParentId());

            return ResponseEntity.ok(ApiResponse.success(FileInfoDTO.from(folder)));
            
        } catch (Exception e) {
            logger.error("创建文件夹失败", e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("创建文件夹失败: " + e.getMessage()));
        }
    }
    
    /**
     * 删除文件
     * DELETE /api/files/{fileId}
     */
    @DeleteMapping("/{fileId}")
    public ResponseEntity<ApiResponse<Void>> deleteFile(@PathVariable Long fileId) {
        try {
            Long userId = SecurityUtils.getCurrentUserId();
            logger.info("用户 {} 删除文件: fileId={}", userId, fileId);
            
            fileManagementService.deleteFile(userId, fileId);
            
            return ResponseEntity.ok(ApiResponse.success("文件删除成功"));
            
        } catch (Exception e) {
            logger.error("删除文件失败: fileId={}", fileId, e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("删除文件失败: " + e.getMessage()));
        }
    }
    
    /**
     * 重命名文件
     * PUT /api/files/{fileId}/rename
     */
    @PutMapping("/{fileId}/rename")
    public ResponseEntity<ApiResponse<FileInfoDTO>> renameFile(
            @PathVariable Long fileId,
            @Valid @RequestBody RenameFileRequest request) {

        try {
            Long userId = SecurityUtils.getCurrentUserId();
            logger.info("用户 {} 重命名文件: fileId={}, newName={}", userId, fileId, request.getNewName());

            FileInfo fileInfo = fileManagementService.renameFile(userId, fileId, request.getNewName());

            return ResponseEntity.ok(ApiResponse.success(FileInfoDTO.from(fileInfo)));
            
        } catch (Exception e) {
            logger.error("重命名文件失败: fileId={}", fileId, e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("重命名文件失败: " + e.getMessage()));
        }
    }
    
    /**
     * 移动文件
     * PUT /api/files/{fileId}/move
     */
    @PutMapping("/{fileId}/move")
    public ResponseEntity<ApiResponse<FileInfoDTO>> moveFile(
            @PathVariable Long fileId,
            @Valid @RequestBody MoveFileRequest request) {

        try {
            Long userId = SecurityUtils.getCurrentUserId();
            logger.info("用户 {} 移动文件: fileId={}, targetParentId={}",
                       userId, fileId, request.getTargetParentId());

            FileInfo fileInfo = fileManagementService.moveFile(userId, fileId, request.getTargetParentId());

            return ResponseEntity.ok(ApiResponse.success(FileInfoDTO.from(fileInfo)));
            
        } catch (Exception e) {
            logger.error("移动文件失败: fileId={}", fileId, e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("移动文件失败: " + e.getMessage()));
        }
    }
    
    /**
     * 获取文件详情
     * GET /api/files/{fileId}
     */
    @GetMapping("/{fileId}")
    public ResponseEntity<ApiResponse<FileInfoDTO>> getFileDetail(@PathVariable Long fileId) {
        try {
            Long userId = SecurityUtils.getCurrentUserId();

            FileInfo fileInfo = fileManagementService.getFileDetail(userId, fileId);

            return ResponseEntity.ok(ApiResponse.success(FileInfoDTO.from(fileInfo)));
            
        } catch (Exception e) {
            logger.error("获取文件详情失败: fileId={}", fileId, e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("获取文件详情失败: " + e.getMessage()));
        }
    }
    
    /**
     * 搜索文件
     * GET /api/files/search
     */
    @GetMapping("/search")
    public ResponseEntity<ApiResponse<FileListResponse>> searchFiles(
            @RequestParam String keyword,
            @RequestParam(required = false) String fileType,
            @RequestParam(required = false) Long parentId,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size) {
        
        try {
            Long userId = SecurityUtils.getCurrentUserId();
            logger.info("用户 {} 搜索文件: keyword={}", userId, keyword);
            
            // 使用文件列表服务进行搜索
            Page<FileInfo> filePage = fileManagementService.getFileList(
                    userId, parentId, page, size, keyword, "updatedAt", "desc");
            
            // 转换为DTO
            List<FileInfoDTO> fileInfoDTOs = filePage.getContent().stream()
                    .map(FileInfoDTO::from)
                    .collect(Collectors.toList());

            // 构建响应
            FileListResponse response = new FileListResponse();
            response.setContent(fileInfoDTOs);
            response.setTotalElements(filePage.getTotalElements());
            response.setTotalPages(filePage.getTotalPages());
            response.setCurrentPage(filePage.getNumber());
            
            return ResponseEntity.ok(ApiResponse.success(response));
            
        } catch (Exception e) {
            logger.error("搜索文件失败", e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("搜索文件失败: " + e.getMessage()));
        }
    }
    
    /**
     * 获取存储统计信息
     * GET /api/files/stats
     */
    @GetMapping("/stats")
    public ResponseEntity<ApiResponse<StorageStatsResponse>> getStorageStats() {
        try {
            Long userId = SecurityUtils.getCurrentUserId();
            
            // 这里可以实现详细的存储统计
            // 暂时返回基本信息
            User user = userRepository.findById(userId).orElse(null);
            
            StorageStatsResponse stats = new StorageStatsResponse();
            if (user != null) {
                stats.setUsedSpace(user.getStorageUsed());
                stats.setTotalSpace(user.getStorageQuota());
                stats.setAvailableSpace(user.getStorageQuota() - user.getStorageUsed());
            }
            
            return ResponseEntity.ok(ApiResponse.success(stats));
            
        } catch (Exception e) {
            logger.error("获取存储统计失败", e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("获取存储统计失败: " + e.getMessage()));
        }
    }
    
    // 私有辅助方法
    
    private double calculateStoragePercentage(Long used, Long quota) {
        if (quota == null || quota == 0) return 0.0;
        return Math.round((double) used / quota * 100 * 100) / 100.0; // 保留两位小数
    }

    /**
     * 映射前端排序字段到数据库字段
     */
    private String mapOrderByField(String orderBy) {
        if (orderBy == null) {
            return "updatedAt";
        }

        return switch (orderBy.toLowerCase()) {
            case "filename", "name" -> "originalName";
            case "filesize", "size" -> "fileSize";
            case "createdat", "created" -> "createdAt";
            case "updatedat", "updated", "time" -> "updatedAt";
            case "relevance" -> "updatedAt"; // 相关度排序暂时用更新时间代替
            default -> "updatedAt";
        };
    }

    /**
     * 高级搜索文件
     * GET /api/files/advanced-search
     */
    @GetMapping("/advanced-search")
    public ResponseEntity<ApiResponse<FileListResponse>> advancedSearchFiles(
            @RequestParam(required = false) String fileName,
            @RequestParam(required = false) String fileTypes,
            @RequestParam(required = false) Long minSize,
            @RequestParam(required = false) Long maxSize,
            @RequestParam(required = false) Long parentId,
            @RequestParam(defaultValue = "updatedAt") String orderBy,
            @RequestParam(defaultValue = "desc") String orderDirection,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size
    ) {
        try {
            logger.info("高级搜索请求 - fileName: {}, fileTypes: {}, parentId: {}, page: {}, size: {}",
                    fileName, fileTypes, parentId, page, size);

            // 构建排序 - 映射前端排序字段到实体字段
            String dbOrderBy = mapOrderByField(orderBy);
            Sort.Direction direction = "asc".equalsIgnoreCase(orderDirection) ?
                Sort.Direction.ASC : Sort.Direction.DESC;
            Sort sort = Sort.by(direction, dbOrderBy);

            // 构建分页
            Pageable pageable = PageRequest.of(page, size, sort);

            // 执行搜索（简化版本，只支持文件名搜索）
            Page<FileInfo> result;
            if (fileName != null && !fileName.trim().isEmpty()) {
                result = fileInfoRepository.globalSearchFiles(fileName.trim(), pageable);
            } else {
                result = fileInfoRepository.findAll(pageable);
            }

            // 转换为DTO
            List<FileInfoDTO> fileInfoDTOs = result.getContent().stream()
                    .map(FileInfoDTO::from)
                    .collect(Collectors.toList());

            FileListResponse response = new FileListResponse();
            response.setContent(fileInfoDTOs);
            response.setTotalElements(result.getTotalElements());
            response.setTotalPages(result.getTotalPages());
            response.setCurrentPage(page);

            logger.info("搜索完成，找到 {} 个文件，总计 {} 个", result.getContent().size(), result.getTotalElements());

            return ResponseEntity.ok(ApiResponse.success(response));
        } catch (Exception e) {
            logger.error("高级搜索失败", e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("搜索失败: " + e.getMessage()));
        }
    }

    /**
     * 复制文件到指定文件夹
     * POST /api/files/{id}/copy-to/{folderId}
     */
    @PostMapping("/{id}/copy-to/{folderId}")
    public ResponseEntity<ApiResponse<FileInfoDTO>> copyFileToFolder(
            @PathVariable Long id,
            @PathVariable Long folderId
    ) {
        try {
            logger.info("复制文件到文件夹 - fileId: {}, targetFolderId: {}", id, folderId);

            // 执行文件复制
            FileInfo copiedFile = fileManagementService.copyFileToFolder(id, folderId);

            FileInfoDTO responseDto = FileInfoDTO.from(copiedFile);

            logger.info("文件复制成功 - 新文件: {} 在文件夹: {}",
                    copiedFile.getOriginalName(), folderId);

            return ResponseEntity.ok(ApiResponse.success(responseDto));
        } catch (Exception e) {
            logger.error("复制文件失败", e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("复制文件失败: " + e.getMessage()));
        }
    }

    /**
     * 复制文件到根目录
     * POST /api/files/{id}/copy-to-root
     */
    @PostMapping("/{id}/copy-to-root")
    public ResponseEntity<ApiResponse<FileInfoDTO>> copyFileToRoot(@PathVariable Long id) {
        try {
            logger.info("复制文件到根目录 - fileId: {}", id);

            // 执行文件复制到根目录 (parentId = null)
            FileInfo copiedFile = fileManagementService.copyFileToFolder(id, null);

            FileInfoDTO responseDto = FileInfoDTO.from(copiedFile);

            logger.info("文件复制到根目录成功 - 新文件: {}", copiedFile.getOriginalName());

            return ResponseEntity.ok(ApiResponse.success(responseDto));
        } catch (Exception e) {
            logger.error("复制文件到根目录失败", e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("复制文件失败: " + e.getMessage()));
        }
    }

    /**
     * 移动文件到指定文件夹
     * PUT /api/files/{id}/move-to/{folderId}
     */
    @PutMapping("/{id}/move-to/{folderId}")
    public ResponseEntity<ApiResponse<FileInfoDTO>> moveFileToFolder(
            @PathVariable Long id,
            @PathVariable Long folderId
    ) {
        try {
            logger.info("移动文件到文件夹 - fileId: {}, targetFolderId: {}", id, folderId);

            // 执行文件移动
            FileInfo movedFile = fileManagementService.moveFileToFolder(id, folderId);

            FileInfoDTO responseDto = FileInfoDTO.from(movedFile);

            logger.info("文件移动成功 - 文件: {} 移动到文件夹: {}",
                    movedFile.getOriginalName(), folderId);

            return ResponseEntity.ok(ApiResponse.success(responseDto));
        } catch (Exception e) {
            logger.error("移动文件失败", e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("移动文件失败: " + e.getMessage()));
        }
    }

    /**
     * 移动文件到根目录
     * PUT /api/files/{id}/move-to-root
     */
    @PutMapping("/{id}/move-to-root")
    public ResponseEntity<ApiResponse<FileInfoDTO>> moveFileToRoot(@PathVariable Long id) {
        try {
            logger.info("移动文件到根目录 - fileId: {}", id);

            // 执行文件移动到根目录 (parentId = null)
            FileInfo movedFile = fileManagementService.moveFileToFolder(id, null);

            FileInfoDTO responseDto = FileInfoDTO.from(movedFile);

            logger.info("文件移动到根目录成功 - 文件: {}", movedFile.getOriginalName());

            return ResponseEntity.ok(ApiResponse.success(responseDto));
        } catch (Exception e) {
            logger.error("移动文件到根目录失败", e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("移动文件失败: " + e.getMessage()));
        }
    }

    /**
     * 批量移动文件
     * PUT /api/files/batch/move
     */
    @PutMapping("/batch/move")
    public ResponseEntity<ApiResponse<Map<String, Object>>> batchMoveFiles(
            @Valid @RequestBody BatchMoveRequest request) {
        try {
            Long userId = SecurityUtils.getCurrentUserId();
            logger.info("批量移动文件 - userId: {}, fileIds: {}, targetParentId: {}",
                       userId, request.getFileIds(), request.getTargetParentId());

            // 执行批量移动
            Map<String, Object> result = fileManagementService.batchMoveFiles(
                userId, request.getFileIds(), request.getTargetParentId());

            logger.info("批量移动文件完成 - 成功: {}, 失败: {}",
                       result.get("successCount"), result.get("failureCount"));

            return ResponseEntity.ok(ApiResponse.success(result));
        } catch (Exception e) {
            logger.error("批量移动文件失败", e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("批量移动文件失败: " + e.getMessage()));
        }
    }


}
